package com.dynaBlaster.game;

import java.util.ArrayList;
import java.util.Random;

import android.util.Log;

import com.dynaBlaster.core.Direction;
import com.dynaBlaster.core.Point;
import com.dynaBlaster.elements.Agent;
import com.dynaBlaster.view.BoardView;
/*
 * Mechanika gry - zalezności geometryczne.
 * 
 */
public class Board {
	
	public static String LOG_TAG = "Board";
	
	public Point size;                 // rozmiar mapy w kostkach
	public int tileSize;               // rozmiar kostki
	
	Tile [][] rows;             // mapa nieruchomych elementow srodowiska 
	
	ArrayList<Agent> agents;  	// obiekty gry ktore podlegaja symulacji
	
	Game game;
	
	public Board(Point size_, Game game){
		this.game = game;
		this.size = new Point();
		this.tileSize = GameConfig.TILE_SIZE;
		this.rows = null;
		this.agents = new ArrayList<Agent>();
		
		reset(size_);
	}
	
	public void setSize(Point s) {
		size = s;
		rows = new Tile[size.y][size.x];	
	}

	/*
	 *  
	 */
	public void reset(Point s) {
		setSize(s);
		
		for (int x = 0; x < size.x; ++x) {
			for (int y = 0; y < size.y; ++y) {
				rows[y][x] = new Tile();
			}
		}
	}

	// obudowuje plansze betonem
	public void initWalls() {
		for (int x = 0; x < size.x; ++x) {
			getTileAtInd(x, 0).terrain = Terrain.CONCRETE;
			getTileAtInd(x, size.y - 1).terrain = Terrain.CONCRETE;
		}
		for (int y = 1; y < size.y - 1; ++y) {
			getTileAtInd(0, y).terrain = Terrain.CONCRETE;;
			getTileAtInd(size.x - 1, y).terrain = Terrain.CONCRETE;;
		}
	}
	
	// zwraca losowe pole typu terenowego
	Point getRandomTileByTerrain(Terrain terrain) {
		int safety_counter = 0;
		int x, y;
		do {
			x = game.random.nextInt(size.x);
			y = game.random.nextInt(size.y);
			
			safety_counter++;
			if (safety_counter > GameConfig.RANDOM_SAFETY_COUNTER)
				break;
		} while (getTileAtInd(x,y).terrain != terrain);

		if (safety_counter > GameConfig.RANDOM_SAFETY_COUNTER) {
			Log.w(LOG_TAG, "getRandomFreeField: brak miejsca,losowanie przerwane ");
			return null;
		}
		return new Point(x, y);
	}
	
	public void initRandomBoard(Point heroIndex, Point exitIndex, Random random) {
		
		Terrain[] probability = new Terrain[] {
			Terrain.WALL, Terrain.WALL, Terrain.WALL, 
			Terrain.FREE, Terrain.FREE,	Terrain.FREE, Terrain.FREE, Terrain.FREE
		};
		
		for (int y = 1; y < size.y - 1; ++y)
			for (int x = 1; x < size.x - 1; ++x) {
				Tile t = new Tile();
				if (x % 2 == 0 && y % 2 == 0) {
					t.terrain = Terrain.CONCRETE;					
				} else {
					int ind = random.nextInt(probability.length);
					t.terrain = probability[ind];
				}
				setTileAtInd(new Point(x,y), t);
			}

		// tam gdzie hero zaczyna musi byc puste
		getTileAtIndex(heroIndex).terrain = Terrain.FREE;
		getTileAtIndex(heroIndex.add(Direction.EAST.asPoint())).terrain = Terrain.FREE;
		getTileAtIndex(heroIndex.add(Direction.SOUTH.asPoint())).terrain = Terrain.FREE;
						
		// exit
		getTileAtIndex(exitIndex).terrain = Terrain.EXIT;
	}
	
	public void load(String data)
	{
		// .  floor
		// W  wall
		// C  concrete
		// 1  hero
		String[] lines = data.split("\n");
		
		// read and set size
		String[] rsize = lines[0].split(" ");
		int size_x = Integer.parseInt(rsize[0]);
		int size_y = Integer.parseInt(rsize[1]);
		
		// reserve memory
		setSize(new Point(size_x, size_y));
		
		// read tile data
		for(int j=0; j < size.y; ++j){
			for(int i=0; i < size.x; ++i){
				Tile tm = new Tile();
				switch (lines[j].charAt(i))
				{
					case '.': tm.terrain = Terrain.FREE; break;
					case 'C': tm.terrain = Terrain.CONCRETE; break;
					case 'W': tm.terrain = Terrain.WALL; break;									
				}
				rows[j][i] = tm;
			}
		}
			
		
	}
	
	
	public Point getTileInd(Point p) {
		return p.divint(tileSize);
	}
	
	public Point getTilePos(Point q) {
		return q.mul(tileSize);
	}
	
	// zwraca tile w punkcie
	public Tile getTileAtPos(Point p) {
		Point q = getTileInd(p);
		return rows[q.y][q.x];		
	}
	

	// zwraca tile przez index
	public Tile getTileAtIndex(Point index) {
		return rows[index.y][index.x];		
	}

	// zwraca tile przez index
	public final Tile getTileAtInd(int x, int y) {
		return rows[y][x];		
	}

	
	// ustawia tile przez index
	public void setTileAtInd(Point index, Tile tile) {
		rows[index.y][index.x] = tile;		
	}
	
	
	public boolean isFree(Point toCheck, boolean allowCreatures, boolean allowWalls) {
		Tile t = getTileAtPos(toCheck);
		if (!allowWalls) {
			if (t.terrain != Terrain.FREE && t.terrain != Terrain.EXIT)
				return false;
		} else if (t.terrain == Terrain.CONCRETE) {
			return false;
		}
		return true;
	}

}

















